/**
   main.cpp - Created by Timothy Morey on 1/27/2012.

   This file provides the primary entry point into the forest fire simulation.
 */

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <string.h>

using namespace std;

#include "simulator.h"
#include "../nvn/nvn-common/cl-args.h"
#include "../nvn/nvn-common/client.h"
#include "../nvn/nvn-common/messages.h"
#include "../nvn/nvn-common/server.h"

Simulator g_Sim(64, 64);

bool ParseCLArgs(int argc, char* argv[], unsigned short& port,
								 unsigned short& width, unsigned short& height);
int ServerRequestReceived(Server* server, 
													const char* clientName,
													const char* recvBuf, int recvLen,
													char* replyBuf, int* replyLen);

int main(int argc, char* argv[])
{
  unsigned short port = 12345;
  unsigned short width = 160;
  unsigned short height = 100;
  
  if(ParseCLArgs(argc, argv, port, width, height))
  {
    Server* controlServer = StartAsyncServer(12345, ServerRequestReceived, ServerModeChatty);
    g_Sim.SetSize(width, height);
    
    while(true)
    {
      string input;
      
      cout << ")))> ";
      getline(cin, input);
      
      if(input == "s")
      {
				if(g_Sim.IsRunning())
					g_Sim.Stop();
				else
					g_Sim.Start();
      }
      else if(input == "ss")
      {
				if(! g_Sim.IsRunning())
					g_Sim.SingleStep();
      }
      else if(input == "p" ||
							input == "print")
      {
				g_Sim.PrintForest();
      }
      else if(input == "rand")
      {
				g_Sim.RandomizeForest();
      }
      else if(input == "q" ||
							input == "quit" ||
							input == "exit")
      {
				break;
      }
    }
    
    g_Sim.Stop();
    StopServer(controlServer);
  }
}

bool ParseCLArgs(int argc, char* argv[], unsigned short& port, 
		 unsigned short& width, unsigned short& height)
{
  bool retval = true;

  ArgDef args[] = 
  {
    { "port", 'p', 1, "The server port." },
    { "width", 'w', 1, "The number of columns in the forest grid." },
    { "height", 'h', 1, "The number of rows in the forest grid." },
    { "help", -1, 0, "Displays information about invoking this application." }
  };
  CLSchema schema = { args, 4 };
  
  if(ValidateArgs(argc, argv, &schema))
  {
    if(ContainsArg(argc, argv, "help", &schema))
    {
      PrintArgSchema(argc, argv, &schema);
      retval = false;
    }
    
    if(ContainsArg(argc, argv, "port", &schema))
      port = atoi(GetArgValue(argc, argv, "port", &schema));
    
    if(ContainsArg(argc, argv, "width", &schema))
      width = atoi(GetArgValue(argc, argv, "width", &schema));
    
    if(ContainsArg(argc, argv, "height", &schema))
      height = atoi(GetArgValue(argc, argv, "height", &schema));
    
    printf("Port: %d\n", port);
    printf("Width: %d\n", width);
    printf("Height: %d\n", height);
  }
  else
  {
    retval = false;
  }

  return retval;
}

int ServerRequestReceived(Server* server,
			  const char* clientName,
			  const char* recvBuf, int recvLen,
			  char* replyBuf, int* replyLen)
{
  int retval = 0;
	MessageType msgType = Unknown;
	char msgName[32];

  printf("%s\n", recvBuf);

	if(IsMessage(recvBuf, recvLen, &msgType, msgName, 32))
	{
		if(0 == strcmp("StartStream", msgName))
		{
			int port;
			char cport[8];
			ParseStartStreamCommand(recvBuf, recvLen, &port);
			sprintf(cport, "%d", port);

			printf("starting data stream to server %s on port %s (%d)...\n", clientName, cport, port);
			Client* client = ConnectAsyncClient(clientName, cport);
			g_Sim.ExportDataToClient(client);
		}
	}
	
  return retval;
}
